﻿using System.Web;
using Castle.Components.DictionaryAdapter.Xml;
using KL.Core.Common.MyOptions;
using KL.Standard.Domain.MessageQueue;
using Microsoft.AspNetCore.Mvc;
using KL.Standard.Domain.Repositories;
using KL.Standard.Model.Attribute;
using KL.Standard.Model.Contant;
using KL.Standard.Model.Infrastructure;
using KL.Standard.Model.Models.BaseArch;
using KL.Standard.Model.ViewModels.Queue;
using KL.Standard.RabbitMQ;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Minio;
using Minio.DataModel.Args;

//using Microsoft.AspNetCore.Hosting.IWebHostEnvironment;

namespace EagCentralPlatform.Net8.Controllers
{
    /// <summary>
    /// 附件管理
    /// </summary>
    [Route("attachment")]
    [ApiController]
    public class AttachmentController : BaseApiController
    {
        private readonly IWebHostEnvironment _hostingEnvironment;
        
        private readonly IAttachRepository _attachRepository;
        
        private readonly MinIOOptions _minIoOptions;
        
        //private readonly IBaseQueueProductor<BASEMQ> _queueProductor;
        
        private readonly AppCustomParaOptions _config;
        
        private readonly IServiceProvider _provider;

        private readonly string _bucketName;

        private ILogger<AttachmentController> _logger;

        public AttachmentController(IWebHostEnvironment hostingEnvironment, IAttachRepository attachRepository,
            IOptions<MinIOOptions> minIoOptions, 
            //IBaseQueueProductor<BASEMQ> queueProductor,
            IOptions<AppCustomParaOptions> options,
            IServiceProvider provider,
            ILogger<AttachmentController> logger)
        {
            this._attachRepository = attachRepository;
            this._hostingEnvironment = hostingEnvironment;
            this._minIoOptions = minIoOptions.Value;
            //this._queueProductor = queueProductor;
            this._config = options.Value;
            this._provider = provider;
            _bucketName = "bbnet8";
            this._logger = logger;
        }
        
        #region 检查桶是否存在

        /// <summary>
        /// 检查桶是否存在
        /// </summary>
        /// <param name="isDelOld"></param>
        /// <param name="uID"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("chkbucketName/{bucketName}")]
        public async Task<BaseResult<string>> CheckBucketName(string bucketName,[FromServices]IMinioClient minioClient)
        {
            bool found = false;
            
            var beArgs = new BucketExistsArgs()
                .WithBucket(bucketName);
            try
            {
                found =  await minioClient.BucketExistsAsync(beArgs);
            }catch (Exception ex)
            {
                _logger.LogError("MinIO bucketExists error:{0}", ex.Message);
            }
            return new BaseResult<string>()
            {
                success = found,
                error = !found?$"[{bucketName}]查找不到":""
            };
        }
        #endregion
        
        
        #region 上传附件(按照配置是否启动minio来判断是保存本地还是MinIO)
        /// <summary>
        /// 上传附件(按照配置是否启动minio来判断是保存本地还是MinIO)
        /// </summary>
        /// <param name="isDelOld"></param>
        /// <param name="uID"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [LogConfig(IsIgnoreRequestTxt = true)]
        [HttpPost("up2/{isDelOld:int}/{uID}")]
        public async Task<BaseResult<string>> BaseImportAttachment(int isDelOld,string uID)
        {
            var files = Request.Form.Files;
            List<SysAttachmentPO> list = new List<SysAttachmentPO>();
            string dataTable = "base_arch_net8";
            //var attachType = "image/png";
            var curUser = this.GetCurUserInfo();
            List<string> batchIdArray = new List<string>();
            var batchId = Guid.NewGuid().ToString();
            foreach (var item in files)
            {
                if (item!=null && item.Length >0)
                {
                    SysAttachmentPO attachmentPo = null;
                    if (!_minIoOptions.Enabled)
                    {
                         attachmentPo = await this.SaveAttachment2Local(loginID: "", file: item,
                            rootPath: _hostingEnvironment.ContentRootPath, moduleName: dataTable, batchId: batchId);
                    }
                    else
                    {
                        attachmentPo =
                            await this.SaveAttachment2MinIO(_provider, _bucketName, "", item, dataTable, batchId);
                    }

                    if (attachmentPo != null)
                    {
                        attachmentPo.mainID = uID;
                        list.Add(attachmentPo);
                    }
                    
                }
            }
            if (list.Count > 0)
            {
                #region 附件记录保存数据库
                if (isDelOld == 1)
                {
                    int _ = await _attachRepository.DeleteAttachment4MainID(uID);
                }
                int count = await _attachRepository.AddAttachment(list);
                #endregion
                
                return new BaseResult<string>()
                {
                    success = count > 0,
                    error = count >0? $"上传{count}个文件成功":"上传失败"
                };
            }
            return new BaseResult<string>()
            {
                success = false,
                error = "无附件上传"
            };
        }
        #endregion
        
        
         #region 导出
        /// <summary>
        /// 导出  
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("download/{uId}")]
        public async Task<IActionResult> Download(string uId,[FromServices]IMinioClient minioClient)
        {
            // /Attachment/SamDev/20230311/41c98529-a80f-49b0-816f-863e9859c4f8.jpg
            var attachmentInfo = await _attachRepository.GetDetailsForId(uId);
            
            if (attachmentInfo != null)
            {
                if (attachmentInfo.isSyn.HasValue && attachmentInfo.isSyn == 1)
                {
                    MemoryStream memoryStream =new MemoryStream();
                    var args = new GetObjectArgs()
                        .WithBucket(_bucketName)
                        .WithObject(attachmentInfo.objectName)
                        .WithCallbackStream(stream => stream.CopyTo(memoryStream));
                   var minIoResponse =await minioClient.GetObjectAsync(args);
                   memoryStream.Seek(0, SeekOrigin.Begin);
                   return File(memoryStream, "application/octet-stream",
                       HttpUtility.UrlEncode(attachmentInfo.fileName + "." + attachmentInfo.fileSuffix,
                           System.Text.Encoding.UTF8));
                }
                else
                {
                    Response.Headers["Access-Control-Expose-Headers"] = "content-disposition";
                    var addrUrl = attachmentInfo.phyAddress;
                    var stream = System.IO.File.OpenRead(addrUrl);
                    //return File(stream, "application/octet-stream", Path.GetFileName(addrUrl));
                    return File(stream, "application/octet-stream",
                        HttpUtility.UrlEncode(attachmentInfo.fileName + "." + attachmentInfo.fileSuffix,
                            System.Text.Encoding.UTF8));
                }
                
            }
            return new JsonResult("找不到可下载的文件");
                     
        }
        #endregion
        
        #region 上传附件
        /// <summary>
        /// 上传附件
        /// </summary>
        /// <param name="isDelOld"></param>
        /// <param name="uID"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [LogConfig(IsIgnoreRequestTxt = true)]
        [HttpPost("up/{isDelOld:int}/{uID}")]
        public async Task<BaseResult<string>> ImportAttachment(int isDelOld,string uID)
        {
            var files = Request.Form.Files;
            string processPath =
                $"{_hostingEnvironment.ContentRootPath}" +
                $"{Path.DirectorySeparatorChar}Attachment{Path.DirectorySeparatorChar}" +
                $"{DateTime.Now.ToString("yyyyMMdd")}";

            List<SysAttachmentPO> list = new List<SysAttachmentPO>();
            string dataTable = "base_arch_net8";
            //var attachType = "image/png";
            var curUser = this.GetCurUserInfo();
            List<string> batchIdArray = new List<string>();
            foreach (var item in files)
            {
                //var processPath = $"{snPath}//{ ConversionPath(item.processPath)}";
                if (!Directory.Exists(processPath))
                {
                    Directory.CreateDirectory(processPath);
                }
                IFormFile file = item;

                if (file != null && file.Length != 0)
                {
                    #region 保存本地&构建附件记录
                    //后缀名
                    string fileExt = file.FileName.Substring(file.FileName.LastIndexOf("."));
                    //                    DirectoryInfo di = new DirectoryInfo(processPath);
                    //                    FileInfo[] oldFiles = di.GetFiles($"*{file.FileName}");
                    string newFileName = $"{(Guid.NewGuid().ToString())}{fileExt}";

                    var filePath = $"{processPath}//{newFileName}";
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await file.CopyToAsync(stream);
                    }
                    var batchId = Guid.NewGuid().ToString();
                    var attachmentPo = new SysAttachmentPO()
                    {
                        dataTable = dataTable,
                        attachType = file.ContentType,
                        fileName = file.FileName.Replace(fileExt, ""),
                        fileSuffix = fileExt.Replace(".", ""),
                        webUrl = "/Attachment/" + DateTime.Now.ToString("yyyyMMdd") + "/" + newFileName,
                        realFileName = newFileName,
                        phyAddress = filePath,
                        creatorID = curUser.loginID,
                        createdTime = DateTime.Now,
                        bldBatchID = batchId,
                        mainID = uID
                    };
                    
                    #endregion

                    #region MinIO 上传
                    if (_minIoOptions.Enabled)
                    {
                        using (var scope = _provider.CreateScope())
                        {
                            
                            var minioClient = scope.ServiceProvider.GetService<IMinioClient>();
                            using (var stream = new MemoryStream())
                            {
                                await file.CopyToAsync(stream);
                                stream.Position = 0;
                                var putObjectArgs = new PutObjectArgs()
                                        .WithBucket(_bucketName)
                                        .WithObject(newFileName)
                                        .WithObjectSize(stream.Length)
                                        .WithStreamData(stream)
                                    ;
                                // .WithObject(attachment.webUrl)
                                // .WithFileName(attachment.phyAddress)
                                // .WithContentType(attachment.attachType);
                                try
                                {
                                    var minIoResponse = await minioClient.PutObjectAsync(putObjectArgs);
                                    _logger.LogInformation("minio Put object Response:{0}",
                                        minIoResponse.ResponseStatusCode);
                                }
                                catch (Exception ex)
                                {
                                    _logger.LogError(ex, "minio Put object error,{0}", ex.StackTrace);
                                }


                                attachmentPo.bucketName = _bucketName;
                                attachmentPo.objectName = newFileName;
                                attachmentPo.isSyn = 1;
                                attachmentPo.synDt = DateTime.Now;
                            }
                        }

                    }
                    #endregion
                    batchIdArray.Add(batchId);
                    list.Add(attachmentPo);
                }
            }
            if (list.Count > 0)
            {
                #region 附件记录保存数据库
                if (isDelOld == 1)
                {
                    int _ = await _attachRepository.DeleteAttachment4MainID(uID);
                }
                int count = await _attachRepository.AddAttachment(list);
                #endregion
                #region 异步发起写入MinIO的任务
                // if (_minIoOptions.Enabled)
                // {
                //     var queueName = $"{_config.SYS_CODE}_MINIO_QUEUE_NAME";
                //     foreach (var batchId in batchIdArray)
                //     {
                //         var msg = new MQueueItem<string>()
                //         {
                //             synModule = SYN_MODULE.ATTACHMENT,
                //             opeType = SYN_OPTTYPE.SAVE,
                //             data = batchId
                //         };
                //         _queueProductor.PublishMsg(msg,queueName,_config.SYS_CODE,MQExchange.DIRECT_MINIO_EXCHANGE);
                //     }
                // }
                #endregion
                return new BaseResult<string>()
                {
                    success = count > 0,
                    error = count >0? $"上传{count}个文件成功":"上传失败"
                };
            }
            return new BaseResult<string>()
            {
                success = false,
                error = "无附件上传"
            };
        }
        #endregion


        #region 附件列表

        /// <summary>
        /// 附件列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("list")]
        public BaseResult<List<object>> List([FromBody] Dictionary<string, string> param)
        {
            // var sarchInfo = new PageSearchModel(param);
            //_log.Debug("invoke /attach/List:" + param);
            var list = _attachRepository.GetAllAttachments(param);
            List<object> result = new List<object>();
            list.ForEach(i =>
            {
                result.Add(new
                {
                    name = i.fileName + "." + i.fileSuffix,
                    url = i.webUrl,
                    uID = i.uID
                });
            });

            return new BaseResult<List<object>>()
            {
                success = true,
                data = result
            };
        }
        #endregion

    }
}